﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using ActivateYourGlutes.Controllers;
using ActivateYourGlutes.Infrastructure;
using ActivateYourGlutes.Services;
using ActivateYourGlutes.Services.Model;
using NUnit.Framework;
using Rhino.Mocks;

namespace ActivateYourGlutes.Tests.Unit.Controllers
{
    [TestFixture]
    public class Test_ErrorLogController : ControllerTestBase
    {
        private ErrorLogController _errorLogController;
        private IErrorLogProvider _errorLogProvider;

        private IEnumerable<Error> _errors;

        [SetUp]
        public override void Init()
        {
            base.Init();
            _errorLogProvider = MockRepository.GenerateMock<IErrorLogProvider>();
            _errorLogController = new ErrorLogController(_commonAccountProvider, _errorLogProvider, _logger);
            _errors = new List<Error>()
                          {
                              new Error()
                                  {
                                      ErrorLevel = ErrorLevelEnum.Warning,
                                      Exception = null,
                                      Id = 1,
                                      Message = "Error One",
                                      Timestamp = DateTime.Now.AddDays(-1)
                                  },
                              new Error()
                                  {
                                      ErrorLevel = ErrorLevelEnum.Error,
                                      Exception = "An exception",
                                      Id = 2,
                                      Message = "Error Two",
                                      Timestamp = DateTime.Now.AddDays(-2)
                                  }
                          };
            _errorLogController.ControllerContext = new ControllerContext(_httpContext, new RouteData(), _errorLogController);
            _errorLogController.LocaleSettings = _localeSettings;
        }

        [Test]
        public void Test_Index_Get_ReturnsView()
        {
            // Act
            ViewResult result = (ViewResult) _errorLogController.Index();
        }

        [Test]
        public void Test_GridData_Get_ReturnsJson()
        {
            // Arrange
            _errorLogProvider.Stub(ep => ep.TotalLogItems()).IgnoreArguments().Return(_errors.Count());
            _errorLogProvider.Stub(ep => ep.LogItems(null, 1, 10)).IgnoreArguments().Return(_errors);

            // Act
            JsonResult result = (JsonResult)_errorLogController.GridData("Date", "Date", 1, 10);

            // Assert
            Assert.That(result.Data, Is.Not.Null);
        }

        [Test]
        public void Test_Detail_Get_ReturnsView()
        {
            // Arrange
            _errorLogProvider.Stub(ep => ep.GetLogItemById(null, 1)).IgnoreArguments().Return(_errors.First());

            // Act
            ViewResult view = (ViewResult)_errorLogController.Detail(1);

            // Assert
            Assert.That(view.ViewData.Model, Is.EqualTo(_errors.First()));
        }

        [Test]
        public void Test_Detail_Get_RedirectsOnUnauthorisedAccess()
        {
            // Arrange
            _errorLogProvider.Stub(ep => ep.GetLogItemById(null, 1)).IgnoreArguments().Throw(
                new AuthorizationException());

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _errorLogController.Detail(1);

            // Assert
            AssertRedirectToUnauthorized(result);
        }

        [Test]
        public void Test_Delete_AjaxDelete_ReturnsTrue()
        {
            // Arrange
            _errorLogProvider.Expect(bp => bp.Delete(null, 0)).IgnoreArguments();
            _httpContext.IsAjaxRequest = true;

            // Act
            JsonResult result = (JsonResult)_errorLogController.Delete(1);

            // Assert
            Assert.That(result.Data, Is.True);
            _errorLogProvider.VerifyAllExpectations();
        }

        [Test]
        public void Test_Delete_AjaxDelete_ReturnsFalseOnUnauthorised()
        {
            // Arrange
            _errorLogProvider.Stub(bp => bp.Delete(null, 0)).IgnoreArguments().Throw(new AuthorizationException());
            _httpContext.IsAjaxRequest = true;

            // Act
            JsonResult result = (JsonResult)_errorLogController.Delete(1);

            // Assert
            Assert.That(result.Data, Is.False);
        }

        [Test]
        public void Test_DeleteAll_Get_ReturnsView()
        {
            ViewResult result = (ViewResult) _errorLogController.DeleteAll();

            Assert.That(result, Is.Not.Null);
        }

        [Test]
        public void Test_DeleteAll_Post_DeletesWhenConfirmed()
        {
            // Arrange
            _errorLogProvider.Expect(bp => bp.Clear(null)).IgnoreArguments();

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _errorLogController.DeleteAll("yes");

            // Assert
            Assert.That(result.RouteValues["controller"], Is.EqualTo("ErrorLog"));
            Assert.That(result.RouteValues["action"], Is.EqualTo("Index"));
            _errorLogProvider.VerifyAllExpectations();
        }

        [Test]
        public void Test_DeleteAll_Post_DoesntDeleteWhenUnconfirmed()
        {
            // Arrange
            _errorLogProvider.AssertWasNotCalled(ep => ep.Clear(Arg<Account>.Is.Anything));

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult) _errorLogController.DeleteAll("no");

            // Assert
            Assert.That(result.RouteValues["controller"], Is.EqualTo("ErrorLog"));
            Assert.That(result.RouteValues["action"], Is.EqualTo("Index"));
            _errorLogProvider.VerifyAllExpectations();
        }

        [Test]
        public void Test_DeleteAll_Post_RedirectsWhenUnauthorized()
        {
            // Arrange
            _errorLogProvider.Stub(ep => ep.Clear(null)).IgnoreArguments().Throw(new AuthorizationException());

            // Act
            RedirectToRouteResult result = (RedirectToRouteResult)_errorLogController.DeleteAll("yes");

            // Assert
            AssertRedirectToUnauthorized(result);
        }
    }
}
